<template>
  <div class="minio-upload">
    <!-- 上传按钮 -->
    <el-button
      :type="buttonType"
      :plain="plain"
      :icon="icon"
      :size="size"
      @click="handleUploadClick"
      :disabled="disabled || uploading"
      :loading="uploading"
      class="upload-trigger"
    >
      <span v-if="!uploading">{{ buttonText }}</span>
      <span v-else>上传中...</span>
    </el-button>

    <!-- 文件上传对话框 -->
    <el-dialog
      v-if="dialogVisible"
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      :width="dialogWidth"
      append-to-body
      :close-on-click-modal="false"
      @close="handleDialogClose"
    >
      <!-- 上传区域 -->
      <div class="upload-area">
        <!-- 上传进度条：仅在上传时显示 -->
        <el-progress
          v-if="showProgress"
          :percentage="uploadPercentage"
          :stroke-width="8"
          class="upload-progress"
        ></el-progress>

        <!-- 文件上传组件 -->
        <el-upload
          class="custom-upload"
          ref="upload"
          action="#"
          :auto-upload="false"
          :on-change="handleFileChange"
          :file-list="fileList"
          :limit="1"
          :accept="acceptMimeTypes"
        :on-exceed="handleExceed"
        :before-remove="beforeRemove"
        >
        <!-- 上传图标和提示文字 -->
        <div class="upload-trigger-inner">
          <i class="el-icon-plus"></i>
          <div class="upload-tip">点击选择图片</div>
        </div>
        </el-upload>
      </div>

      <!-- 上传提示 -->
      <div class="upload-hint">
        <span class="required-star">*</span>
        支持上传 {{ acceptExtText }} 格式图片，
        单个文件大小不超过 {{ fileSizeLimit }}MB，仅支持上传 1 个文件
        <span style="color:#67c23a;">（图片将自动压缩处理）</span>
      </div>

      <!-- 对话框底部按钮 -->
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button
          type="primary"
          @click="submitUpload"
          :disabled="!canUpload"
        >
          上 传
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { uploadFile } from '@/api/upload/minioFile'
import ImageCompressor from 'image-compressor.js'
import { ACCEPT_CONFIG } from '@/components/MinioFileUpload/config/accept'

// 后缀名映射MIME类型（仅保留ACCEPT_CONFIG.image涉及的类型，避免冗余）
const EXT_TO_MIME = {
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.jpeg': 'image/jpeg',
  '.gif': 'image/gif',
  '.bmp': 'image/bmp'
}

export default {
  name: 'ImageUpload',
  props: {
    buttonText: {
      type: String,
      default: '上传图片'
    },
    buttonType: {
      type: String,
      default: 'primary'
    },
    plain: {
      type: Boolean,
      default: true
    },
    icon: {
      type: String,
      default: 'el-icon-upload'
    },
    size: {
      type: String,
      default: 'mini'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    dialogTitle: {
      type: String,
      default: '图片上传'
    },
    dialogWidth: {
      type: String,
      default: '500px'
    },
    fileSizeLimit: {
      type: Number,
      default: 5
    },
    compressOptions: {
      type: Object,
      default: () => ({
        quality: 0.8,
        maxWidth: 1920,
        maxHeight: 1080,
        convertSize: 1024 * 1024,
        success: (result) => console.log('压缩成功', result),
        error: (err) => console.error('压缩失败', err)
      })
    }
  },
  data() {
    return {
      dialogVisible: false,
      fileList: [],
      selectedFile: null,
      compressedFile: null,
      uploading: false,
      uploadPercentage: 0,
      showProgress: false
    }
  },
  computed: {
    // 动态生成el-upload需要的MIME类型（替代原setAcceptByGroup方法+currentAccept）
    acceptMimeTypes() {
      return ACCEPT_CONFIG.image
        .map(ext => EXT_TO_MIME[ext.toLowerCase()])
        .filter(Boolean)
        .join(',')
    },
    // 动态生成上传提示的格式文本（替代原formatAcceptText方法）
    acceptExtText() {
      return ACCEPT_CONFIG.image
        .map(ext => ext.slice(1).toUpperCase()) // 移除后缀点（.png→PNG）
        .join('、')
    },
    canUpload() {
      return !!this.selectedFile && !this.uploading
    }
  },
  methods: {
    // 重置文件选择状态
    resetFileSelection() {
      this.fileList = []
      this.selectedFile = null
      this.compressedFile = null
      this.$refs.upload?.clearFiles() // 可选链避免 refs 不存在时报错
      this.uploadPercentage = 0
      this.showProgress = false
    },

    // 打开上传对话框
    handleUploadClick() {
      this.resetUploadState()
      this.dialogVisible = true
    },

    // 处理文件选择变化
    handleFileChange(file, fileList) {
      // 1. 校验文件大小
      if (file.size > this.fileSizeLimit * 1024 * 1024) {
        this.$message.error(`文件 ${file.name} 大小超过${this.fileSizeLimit}MB限制`)
        this.resetFileSelection()
        return
      }

      // 2. 校验文件格式（基于ACCEPT_CONFIG.image，比原MIME校验更精准）
      const fileExt = `.${file.raw.name.split('.').pop().toLowerCase()}`
      if (!ACCEPT_CONFIG.image.includes(fileExt)) {
        this.$message.error(`请选择${this.acceptExtText}格式的图片文件`)
        this.resetFileSelection()
        return
      }

      // 3. 只保留最后一个文件
      const lastFile = fileList.slice(-1)[0]
      this.fileList = lastFile ? [lastFile] : []
      this.selectedFile = lastFile?.raw || null

      // 4. 自动压缩图片
      this.selectedFile && this.compressImage(this.selectedFile)
    },

    // 处理文件超出限制
    handleExceed(files, fileList) {
      this.$message.warning('每次只能上传一个文件，请先移除已选择的文件')
      const lastFile = fileList.slice(-1)[0]
      this.fileList = [lastFile]
      this.selectedFile = lastFile?.raw
      this.selectedFile && this.compressImage(this.selectedFile)
    },

    // 移除文件前的确认
    beforeRemove(file) {
      return this.$confirm(`确定要移除 ${file.name} 吗？`)
    },

    // 图片压缩处理
    compressImage(file) {
      this.$modal.loading("正在压缩图片，请稍候...")
      new ImageCompressor(file, {
        ...this.compressOptions,
        success: (result) => {
          this.$modal.closeLoading()
          this.compressedFile = result
        },
        error: (err) => {
          this.$modal.closeLoading()
          this.$message.error(`图片压缩失败: ${err.message || '未知错误'}`)
          this.compressedFile = file // 压缩失败保留原文件
        }
      })
    },

    // 提交上传
    submitUpload() {
      if (!this.selectedFile) {
        this.$message.error("请选择图片文件")
        return
      }

      const uploadFile = this.compressedFile || this.selectedFile
      this.startNormalUpload(uploadFile)
    },

    // 普通上传（带进度条）
    startNormalUpload(file) {
      const formData = new FormData()
      formData.append('file', file)

      this.uploading = true
      this.showProgress = true // 上传开始显示进度条
      this.$modal.loading("正在上传文件，请稍候...")

      uploadFile(formData).then(response => {
        this.handleUploadSuccess(response)
      }).catch(error => {
        this.handleUploadError(error)
      })
    },

    // 上传成功处理
    handleUploadSuccess(response) {
      this.uploading = false
      this.showProgress = false
      this.$modal.closeLoading()
      this.$modal.msgSuccess("图片上传成功")
      this.$emit('upload-success', response.data)
      setTimeout(() => this.dialogVisible = false, 1000)
    },

    // 上传失败处理
    handleUploadError(error) {
      this.uploading = false
      this.showProgress = false
      this.$modal.closeLoading()
      this.$modal.msgError(`图片上传失败: ${error.msg || error.message || '未知错误'}`)
      this.$emit('upload-error', error)
    },

    // 关闭对话框时重置状态
    handleDialogClose() {
      this.resetUploadState()
    },

    // 重置上传状态（合并原resetFileSelection逻辑，避免重复）
    resetUploadState() {
      this.resetFileSelection()
      this.uploading = false
    }
  }
}
</script>

<style scoped>
/* 整体容器：内联块级元素，与周边内容对齐 */
.minio-upload {
  display: inline-block;
  margin-right: 10px;
}

/* 上传触发按钮：类似avatar-uploader样式 */
.upload-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 120px;
  padding: 8px 16px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s ease;
  background-color: #fff;
}

.upload-trigger:hover {
  border-color: #409EFF;
  color: #409EFF;
}

.upload-trigger:disabled {
  border-color: #e6e6e6;
  color: #c0c4cc;
  cursor: not-allowed;
  background-color: #fafafa;
}

/* 上传区域：卡片式布局 */
.upload-area {
  padding: 20px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  background-color: #fafafa;
  margin-bottom: 15px;
  text-align: center;
}

.upload-area:hover {
  border-color: #409EFF;
}

/* 自定义上传组件布局 */
.custom-upload {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* 上传触发内部：图标+提示 */
.upload-trigger-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.upload-trigger-inner .el-icon-plus {
  font-size: 48px;
  color: #8c939d;
}

.upload-trigger-inner .upload-tip {
  font-size: 14px;
  color: #606266;
  line-height: 1.5;
}

/* 上传进度条间距 */
.upload-progress {
  margin-bottom: 15px;
}

/* 上传提示样式 */
.upload-hint {
  margin-bottom: 20px;
  padding: 10px;
  border: 1px solid #e6f3ff;
  border-radius: 4px;
  background-color: #f0f9ff;
  color: #333;
  font-size: 12px;
  line-height: 1.6;
}

.upload-hint .required-star {
  color: #f56c6c;
  font-weight: bold;
  margin-right: 2px;
}

/* 对话框底部按钮间距 */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding-top: 10px;
  border-top: 1px solid #ebeef5;
}

</style>
